package com.kudian.restful.controller;

import com.kudian.common.persistence.ResultObj;
import com.kudian.common.utils.MD5;
import com.kudian.common.utils.PropertiesLoader;
import com.kudian.common.utils.StringUtils;
import com.kudian.common.utils.UUIDGenerator;
import com.kudian.pay.HttpsUtils;
import com.kudian.restful.entity.LoginSession;
import com.kudian.restful.service.CartService;
import com.kudian.restful.service.LoginSessionService;
import com.kudian.restful.service.OrderService;
import com.kudian.restful.service.PayLogService;
import com.kudian.restful.vo.cart.AddCartInfoVO;
import com.kudian.restful.vo.cart.QueryCartInfoRetVO;
import com.kudian.restful.vo.cart.QueryCartInfoVO;
import com.kudian.restful.vo.order.DetailOrderRetVO;
import com.kudian.restful.vo.order.DetailOrderVO;
import com.kudian.restful.vo.order.OrderVO;
import com.kudian.restful.vo.pay.AliPayOrderVO;
import com.kudian.restful.vo.pay.BookInfo;
import com.kudian.restful.vo.pay.PayOrderVO;
import com.wordnik.swagger.annotations.ApiOperation;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/4/27.
 */
@RestController
@RequestMapping("pay")
public class PayController {

    private static final Logger logger = Logger.getLogger(PayController.class);

    private static final String appid = "wxd381916cf0bbf29d";

    private static final String mch_id = "1339045001";

    @Autowired
    private OrderService orderService;

    @Autowired
    private LoginSessionService loginSessionService;

    @Autowired
    private PayLogService payLogService;

    @RequestMapping(value = "bookorder", method = RequestMethod.GET)
    public JSONObject bookorder() {
        // BookInfo bi = new BookInfo();
        JSONObject o = new JSONObject();

//        StringBuffer sb = new StringBuffer();
//        sb.append("<xml>");
//        sb.append("	<appid>wxd381916cf0bbf29d</appid>");
//        sb.append("	<attach>test</attach>");
//        sb.append("	<body>APPtest</body>");
//        sb.append("	<mch_id>1339045001</mch_id>");
//        sb.append("	<nonce_str>65c8fac043994edd8fcdad587c8dc6c1</nonce_str>");
//        sb.append("	<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>");
//        sb.append("	<out_trade_no>1415659990</out_trade_no>");
//        sb.append("	<total_fee>1</total_fee>");
//        sb.append("	<trade_type>APP</trade_type>");
//        sb.append("	<sign>641102A7CE7BCA933C261E31ECF62F4B</sign>");
//        sb.append("</xml>");

//        StringBuffer sb = new StringBuffer();
//        sb.append("<xml>");
//        sb.append("	<appid>wxd381916cf0bbf29d</appid>");
//        sb.append("	<attach>test</attach>");
//        sb.append("	<body>APPtest</body>");
//        sb.append("	<mch_id>1339045001</mch_id>");
//        sb.append("	<nonce_str>65c8fac043994edd8fcdad587c8dc6c1</nonce_str>");
//        sb.append("	<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>");
//        sb.append("	<out_trade_no>20160619000003</out_trade_no>");
//        sb.append("	<total_fee>1</total_fee>");
//        sb.append("	<trade_type>APP</trade_type>");
//        sb.append("	<sign>B670D1ED3597D235B1DC72D6404A0836</sign>");
//        sb.append("</xml>");

        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        sb.append("	<appid>wxd381916cf0bbf29d</appid>");
        sb.append("	<attach>test</attach>");
        sb.append("	<body>APPtest</body>");
        sb.append("	<mch_id>1339045001</mch_id>");
        sb.append("	<nonce_str>65c8fac043994edd8fcdad587c8dc6c1</nonce_str>");
        sb.append("	<notify_url>http://101.201.74.2/pay/wxback</notify_url>");
        sb.append("	<out_trade_no>20160619000006</out_trade_no>");
        sb.append("	<total_fee>1</total_fee>");
        sb.append("	<trade_type>APP</trade_type>");
        sb.append("	<sign>7902E3B64F9CC12F44756A2EC774A350</sign>");
        sb.append("</xml>");

        // 本地起的https服务
        String httpsUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        // 密码
        String password = "123456";
        // 密钥库
        String keyStorePath = "/opt/soft/key/tomcat.keystore";
        // 信任库
        String trustStorePath = "/opt/soft/key/tomcat.keystore";

        HttpsUtils uts = new HttpsUtils(password, keyStorePath, trustStorePath);
        String r = uts.post(httpsUrl, sb.toString());
        logger.info("返回报文:" + r);

        try {
            SAXReader reader = new SAXReader();
            Document doc;
            doc = DocumentHelper.parseText(r);

            String returncode = doc.selectSingleNode("/xml/return_code").getText();
            String returnmsg = doc.selectSingleNode("/xml/return_msg").getText();
            String appid = doc.selectSingleNode("/xml/appid").getText();
            String mch_id = doc.selectSingleNode("/xml/mch_id").getText();
            String nonce_str = doc.selectSingleNode("/xml/nonce_str").getText();
            String sign = doc.selectSingleNode("/xml/sign").getText();
            String result_code = doc.selectSingleNode("/xml/result_code").getText();
            String prepay_id = doc.selectSingleNode("/xml/prepay_id").getText();
            String trade_type = doc.selectSingleNode("/xml/trade_type").getText();

            StringBuffer sbf = new StringBuffer();
            String timestamp = System.currentTimeMillis() / 1000 + "";
            sbf.append("appid=");
            sbf.append(appid);
            sbf.append("&noncestr=");
            sbf.append(nonce_str);
            sbf.append("&package=");
            sbf.append("Sign=WXPay");
            sbf.append("&partnerid=");
            sbf.append(mch_id);
            sbf.append("&prepayid=");
            sbf.append(prepay_id);
            sbf.append("&timestamp=");
            sbf.append(timestamp);
            sbf.append("&key=b4eaea65dd014bc9ad8a9e881dd85a36");

            String s11 = MD5.getMessageDigest(sbf.toString().getBytes());

            o.put("appid", appid);
            o.put("noncestr", nonce_str);
            o.put("package", "Sign=WXPay");
            o.put("partnerid", mch_id);
            o.put("prepayid", prepay_id);
            o.put("timestamp", timestamp);
            o.put("sign", s11.toUpperCase());
//            bi.setReturn_code(doc.selectSingleNode("/xml/return_code").getText());
//            bi.setReturn_msg(doc.selectSingleNode("/xml/return_msg").getText());
//            bi.setAppid(doc.selectSingleNode("/xml/appid").getText());
//            bi.setMch_id(doc.selectSingleNode("/xml/mch_id").getText());
//            bi.setNonce_str(doc.selectSingleNode("/xml/nonce_str").getText());
//            bi.setSign(doc.selectSingleNode("/xml/sign").getText());
//            bi.setResult_code(doc.selectSingleNode("/xml/result_code").getText());
//            bi.setPrepay_id(doc.selectSingleNode("/xml/prepay_id").getText());
//            bi.setTrade_type(doc.selectSingleNode("/xml/trade_type").getText());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return o;
    }

    @RequestMapping(value = "wxPayorder", method = RequestMethod.POST)
    @ApiOperation(value = "微信支付订单", httpMethod = "POST", notes = "微信支付订单", response = JSONObject.class)
    public @ResponseBody JSONObject wxPayorder(@RequestBody DetailOrderVO vo) {
        JSONObject o = new JSONObject();

        if (vo == null || StringUtils.isBlank(vo.getAccess_token())) {
            return o;
        }
        LoginSession ent = loginSessionService.getInfo(vo.getAccess_token());
        if (ent == null) {
            return o;
        }

        try {
            List<OrderVO> orders = orderService.details(vo);
            o = creAndSendPayOrder(orders);
        } catch (Exception e) {
            logger.error(e);
        }
        return o;
    }

    /**
     * 创建订单信息
     * @param orders
     * @return
     */
    private JSONObject creAndSendPayOrder(List<OrderVO> orders) {
        PropertiesLoader p = new PropertiesLoader("env.properties");
        String password = p.getProperty("PASSWORD");
        String keyStorePath = p.getProperty("KEYSTOREPATH");
        String trustStorePath = p.getProperty("TRUSTSTOREPATH");
        String httpsUrl = p.getProperty("HTTPSURL");
        String wxnotifyurl = p.getProperty("WX_NOTIFY_URL");

        // 接口定义中,表示 附加数据
        String attach = "jisuan";
        String body = "酷点帮帮";
        // String body = "先客";
        String detail = "";
        String nonce_str = "";
        String out_trade_no = "";
        String total_fee = "";
        String sign = "";

        double total = 0;
        boolean first = true;
        List<Integer> orderIds = new ArrayList<Integer>();
        for (OrderVO order : orders) {
            orderIds.add(order.getOrderId());
            // 应付款项合计
            total += order.getOrderAmount();
            if (first) {
                detail = detail + order.getOrderSn();
                first = false;
            } else {
                detail = detail + "\n" + order.getOrderSn();
            }
        }

        nonce_str = UUIDGenerator.getUUID();
        // 此值为订单号
        out_trade_no = UUIDGenerator.getUUID();

        //
        payLogService.addPayLog(out_trade_no, orderIds, (short) 2);
        total_fee = String.valueOf((int) (total * 100));
        StringBuffer sbsign = new StringBuffer();
        sbsign.append("appid=" + appid);
        sbsign.append("&attach=" + attach);
        sbsign.append("&body=" + body);
        sbsign.append("&detail=" + detail);
        sbsign.append("&mch_id=" + mch_id);
        sbsign.append("&nonce_str=" + nonce_str);
        sbsign.append("&notify_url=" + wxnotifyurl);
        sbsign.append("&out_trade_no=" + out_trade_no);
        sbsign.append("&total_fee=" + total_fee);
        sbsign.append("&trade_type=APP");
        sbsign.append("&key=b4eaea65dd014bc9ad8a9e881dd85a36");
        logger.info("sbsign==>" + sbsign.toString());
        try {
            sign = MD5.getMessageDigest(sbsign.toString().getBytes()).toUpperCase();
        } catch (Exception e) {
            logger.error(e);
        }
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        sb.append("	<appid>" + appid + "</appid>");
        sb.append("	<attach><![CDATA[" + attach + "]]></attach>");
        sb.append("	<body><![CDATA[" + body + "]]></body>");
        sb.append("	<detail><![CDATA[" + detail + "]]></detail>");
        sb.append("	<mch_id>" + mch_id + "</mch_id>");
        sb.append("	<nonce_str>" + nonce_str + "</nonce_str>");
        sb.append("	<notify_url>" + wxnotifyurl + "</notify_url>");
        sb.append("	<out_trade_no>" + out_trade_no + "</out_trade_no>");
        sb.append("	<total_fee>" + total_fee + "</total_fee>");
        sb.append("	<trade_type>APP</trade_type>");
        sb.append("	<sign>" + sign + "</sign>");
        sb.append("</xml>");

        logger.info("sb==>" + sb.toString());
        HttpsUtils uts = new HttpsUtils(password, keyStorePath, trustStorePath);
        String r = uts.post(httpsUrl, sb.toString());
        logger.info("返回报文:" + r);

        JSONObject o = retObject(r); // JSONObject();
        return o;
    }

    /**
     * 将返回xml转换为jsonobject
     *
     * @param r
     * @return
     */
    private JSONObject retObject(String r) {

        logger.info("返回报文:" + r);
        JSONObject o = new JSONObject();
        try {
            SAXReader reader = new SAXReader();
            Document doc;
            doc = DocumentHelper.parseText(r);

            String returncode = doc.selectSingleNode("/xml/return_code").getText();
            String returnmsg = doc.selectSingleNode("/xml/return_msg").getText();
            String appid = doc.selectSingleNode("/xml/appid").getText();
            String mch_id = doc.selectSingleNode("/xml/mch_id").getText();
            String nonce_str = doc.selectSingleNode("/xml/nonce_str").getText();
            String sign = doc.selectSingleNode("/xml/sign").getText();
            String result_code = doc.selectSingleNode("/xml/result_code").getText();
            String prepay_id = doc.selectSingleNode("/xml/prepay_id").getText();
            String trade_type = doc.selectSingleNode("/xml/trade_type").getText();

            StringBuffer sbf = new StringBuffer();
            String timestamp = System.currentTimeMillis() / 1000 + "";
            sbf.append("appid=");
            sbf.append(appid);
            sbf.append("&noncestr=");
            sbf.append(nonce_str);
            sbf.append("&package=");
            sbf.append("Sign=WXPay");
            sbf.append("&partnerid=");
            sbf.append(mch_id);
            sbf.append("&prepayid=");
            sbf.append(prepay_id);
            sbf.append("&timestamp=");
            sbf.append(timestamp);
            sbf.append("&key=b4eaea65dd014bc9ad8a9e881dd85a36");

             sign = MD5.getMessageDigest(sbf.toString().getBytes());

            o.put("appid", appid);
            o.put("noncestr", nonce_str);
            o.put("package", "Sign=WXPay");
            o.put("partnerid", mch_id);
            o.put("prepayid", prepay_id);
            o.put("timestamp", timestamp);
            o.put("sign", sign.toUpperCase());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return o;
    }

    @RequestMapping(value = "wxback")
    public @ResponseBody String wxback(HttpServletRequest request) {
logger.info("in wxback------>" + request.getMethod());

        String str = "";
        try {
            request.setCharacterEncoding("UTF-8");
            StringBuffer jb = new StringBuffer();
            String line = null;

            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                jb.append(line);
            }

            SAXReader saxReader = new SAXReader();
            Document doc;
            doc = DocumentHelper.parseText(jb.toString());

            String out_trade_no = doc.selectSingleNode("/xml/out_trade_no").getText();
            // 更新对应的订单id
            this.payLogService.savePayLog(out_trade_no);

            // TODO 支付完成可以扣除库存
            // TODO 微信支付时有问题,微信不能接收到正确的返回信息
//            str = "<xml>\n" +
//                    "<return_code>\n" +
//                    "<![CDATA[ SUCCESS ]]>\n" +
//                    "</return_code>\n" +
//                    "<return_msg>\n" +
//                    "<![CDATA[ OK ]]>\n" +
//                    "</return_msg>\n" +
//                    "</xml>";
            str = "SUCCESS";
        } catch (Exception e) {
            logger.error(e);
        }
        return str;
    }

    /**
     * 支付宝的前段生成的out_trade_no,与系统中的订单id关联
     * @param vo
     * @return
     */
    @RequestMapping(value = "relation", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ApiOperation(value = "关联订单", httpMethod = "POST", notes = "支付宝的前段生成的out_trade_no,与系统中的订单id关联", response = ResultObj.class)
    public @ResponseBody ResultObj relation(@RequestBody AliPayOrderVO vo) {
        ResultObj o = new ResultObj();
        if (vo == null || StringUtils.isBlank(vo.getAccess_token())) {
            o.setErrcode(9999);
            o.setErrmsg("关联订单失败!access_token为空");
            return o;
        }

        try {
            LoginSession ent = loginSessionService.getInfo(vo.getAccess_token());
            if (ent == null) {
                o.setErrcode(9999);
                o.setErrmsg("access_token已失效!");
                return o;
            }

            o.setErrcode(0);
            o.setErrmsg("提交订单信息成功!");
            this.payLogService.addPayLog(vo.getOutTradeNo(), vo.getOrderIds(), (short) 1);
        } catch (Exception e) {
            logger.error(e);
            o.setErrcode(9999);
            o.setErrmsg("提交订单信息失败!");
        }
        return o;
    }
}
